import * as fs from 'fs';

import { Application } from 'egg';

import { Apollo as NativeApollo } from '@gaoding/apollo-client';

import { IApolloConfig } from '@gaoding/apollo-client/dist/interface/IApolloConfig';
import { tmpdir } from 'os';
import * as path from 'path';
import { EnvWriter } from './env_writer';
import { EnvReader } from './env_reader';

export interface ApolloReponseConfigData {
    // '{"appId":"ums-local","cluster":"default","namespaceName":"application","configurations":{"NODE_ENV":"production"}
    appId: string;
    cluster: string;
    namespaceName: string;
    configurations: {
        [x: string]: string;
    };
    releaseKey: string;
}

export default class Apollo extends NativeApollo {
    app: Application;

    constructor(config: IApolloConfig, app: Application) {
        super(config, app.logger);
        this.app = app;
    }

    get config_server_url() {
        return super.config_server_url;
    }

    get app_id() {
        return super.app_id;
    }

    get secret() {
        return super.secret;
    }

    get token() {
        return super.token;
    }

    get portal_address() {
        return super.portal_address;
    }

    get cluster_name() {
        return super.cluster_name;
    }

    get namespace_name() {
        return super.namespace_name;
    }

    get release_key() {
        return super.release_key;
    }

    get ip() {
        return super.ip;
    }

    get watch() {
        return super.watch;
    }

    get env_file_path() {
        return super.env_file_path;
    }

    get env_file_type() {
        return super.env_file_type;
    }

    get set_env_file() {
        return super.set_env_file;
    }

    get init_on_start() {
        return super.init_on_start;
    }

    get configs() {
        return super.configs;
    }

    get apollo_env() {
        return super.apollo_env;
    }

    get notifications() {
        return super.notifications;
    }

    get delay() {
        return super.delay;
    }

    get timeout() {
        return super.timeout;
    }

    get envReader() {
        return super.envReader;
    }

    get openApi() {
        return super.openApi;
    }

    get(key: string) {
        const configs = this.configs;

        return configs.get(key);
    }

    getString(key: string) {
        return this.configs.getString(key);
    }

    getNumber(key: string) {
        return this.configs.getNumber(key);
    }

    getBoolean(key: string) {
        return this.configs.getBoolean(key);
    }

    getJSON(key: string) {
        return this.configs.getJSON(key);
    }

    getDate(key: string) {
        return this.configs.getDate(key);
    }

    protected checkEnvPath(envPath?: string): string {
        const baseDir = tmpdir();
        if (!envPath) {
            return baseDir;
        } else {
            if (!path.isAbsolute(envPath)) {
                // envPath = envPath.replace('/', '');
                envPath = path.resolve(baseDir, envPath);
            }

            if (fs.existsSync(envPath)) {
                return envPath;
            } else {
                const last = envPath.split('/').pop();
                if (last && last.indexOf('.') > -1) {
                    // 如果 env path 是一个文件路径
                    const dir = envPath.replace(new RegExp(`${last}$`), '');
                    if (!fs.existsSync(dir)) {
                        //  创建前置文件夹
                        fs.mkdirSync(dir);
                    }
                    return dir;
                } else {
                    // 如果 env path 是一个文件夹路径
                    fs.mkdirSync(envPath);
                    return envPath;
                }
            }
        }
    }

    protected saveEnvFile(data: ApolloReponseConfigData) {
        if (!(this.app.type === 'agent'))
            return;

        const { configurations, namespaceName, releaseKey } = data;

        this.apollo_env.release_key = releaseKey;
        for (const key in configurations) {
            this.apollo_env[`${namespaceName}.${key}`] = configurations[key];
        }

        new EnvWriter({
            env_file_type: this.env_file_type,
            env_file_path: this.env_file_path,
            logger: this.logger
        }).write(data);
    }

    protected readFromEnvFile(envPath: string = this.env_file_path): void {
        if (this.app.type === 'agent')
            return;
        // 查找当前目录下所有的命名空间

        const envReader = new EnvReader({
            env_file_type: this.env_file_type,
            env_file_path: this.env_file_path,
            logger: this.logger
        });
        const manifest = envReader.loadManifest();
        if (manifest) {
            Object.keys(manifest).forEach(ns => {
                const configs = envReader.readEnvFromFile(path.resolve(envPath, `.env.apollo.${ns}`), ns);
                if (configs) {
                    for (const namespaceKey in configs) {
                        let config = this.configs.configs[namespaceKey];
                        const configurations = configs[namespaceKey];

                        if (!config) {
                            config = new Map();
                        }

                        for (const key in configurations) {
                            const configuration = configurations[key];
                            process.env[`${namespaceKey}.${key}`] = configuration;
                            config.set(key, configuration);
                        }
                        this.configs.configs[namespaceKey] = config;
                    }
                }
            })
        }
    }
}
